1 - Análise exploratória de dados#

Este material foi adaptado de [MagalhaesdL02] e [Mar15].

Definições básicas#

O que é estatística?\(^1\)#

Estatística é um conjunto de técnicas para, sistematicamente:

  • Planejar a coleta de dados oriundos de estudos ou experimentos, realizados em qualquer área do conhecimento;

  • Descrever, analisar e interpretar dados;

  • Extrair informações para subsidiar decisões;

  • Avaliar evidências empíricas sob hipóteses de interesse.

\(^1\) http://www.leg.ufpr.br/

Exemplos de aplicações:#

  • Opinião da população brasileira sobre o novo governo.

  • Avaliar a efetividade de uma nova droga para a cura do câncer.

  • Entender os hábitos de compra dos clientes de uma loja virtual.

  • Recomendação personalizada de produtos.

  • Comparar a produtividade da soja sob diferentes formas de cultivo, adubação, etc.

Conceitos fundamentais#

  • População: Conjunto de todos os elementos sob investigação.

  • Amostra: Subconjunto da população.

  • Variável de interesse: característica a ser observada em cada indivíduo da amostra.

Divisões básicas da estatística#

image.png

Exemplo 1: Opinião da população brasileira sobre o novo governo.

  • População: Todos os habitantes do Brasil? outras opções?

  • Amostra: Algum subconjunto da população. Qualquer um será? Como selecionar?

  • Variável de interesse: Opinião sobre o novo governo. Como medir isso? Gosta? sim ou não.

Exemplo 2: Avaliar a efetividade de uma nova droga para a cura do câncer.

  • População: Todos os seres humanos? Apenas os já doentes? Como levar em conta questões de raça, culturas, etc …

  • Amostra: E agora?

  • Variável de interesse: Curou ou não curou? Será que isso é possível?

Exemplo 3: Entender os hábitos de compra dos clientes de uma loja virtual.

  • População: Todos os clientes da loja virtual.

  • Amostra: Preciso de amostra?

  • Variável de interesse: E agora? Como caracterizar hábito de compra?

Desenho de estudos#

image.png

Estudos caso-controle#

De uma mesma população são selecionadas amostras de indivíduos portadores de uma condição (casos) e outra de indivíduos não portadores (controle). Se há maior frequência de exposição a uma situação entre os indivíduos portadores, temos um indício de que a exposição está relacionada à condição de interesse.

image.png

Estudos transversais#

Seleciona-se uma amostra da população em questão, e posteriormente, verificamos quem é portador ou não da característica de interesse (por exemplo, doença). Objetiva-se obter uma estimativa da proporção de pessoas portadoras da característica. Como todas as informações da amostra são obtidas em um mesmo instante, pode ser difícil entender se a característica de interesse surgiu antes ou depois da exposição.

image.png

Estudos de coorte#

Os indivíduos amostados são classificados como expostos ou não a uma situação que pode (ou não) ocasionar um evento específico (como uma doença). Esses individuos são acompanhados durante um período, e se ocorrer um mais eventos entre indivíduos expostos, temos evidências que a exposição pode ocasionar aquele evento.

image.png

Estudos de intervenção#

Objetiva-se administrar um tipo de intervenção capaz de alterar algum aspecto dos indivíduos, como o estado de saúde. Os estudos podem ser caracterizados como profiláticos ou terapêuticos. Um tipo de intervenção comum é o ensaio controlado aleatorizado, em que os indivíduos elegíveis ao estudo são divididos ao acaso em dois ou mais grupos. O grupo que não recebe a intervenção, ou tratamento, é geralmente denominado grupo controle. Outro tipo de estudo de intervenção é chamado de ensaio de não superioridade, cujo objetivo é entender se a intervenção estudada é tão benéfica quanto outra tradicionalmente utillizada no tratamento de uma condição.

Planejamento da coleta dos dados#

Coleta de dados por amostragem

  • Definição da população e característica de interesse.

  • Definição do plano amostral:

    • Aleatória simples (com ou sem reposição) ou sistemática;

    • Estratificada, por estratos da população (segundo uma característica);

    • Conglomerados, por grupos de indivíduos da população (subpopulações);

    • Amostragem complexa (combina anteriores).

Divisões essenciais em Estatı́stica e seus principais objetivos.#

Estatı́stica descritiva ou exploratória:

  • Consistência dos dados e interpretações iniciais.

  • Visualização dos dados e relações entre variáveis.

Probabilidade:

  • Fornece ferramentas para lidar/quantificar incerteza.

Inferência estatı́stica:

  • Estimação de quantidades desconhecidas.

  • Formular e testar hipóteses.

  • Extrapolar para a população resultados obtidos na amostra.

image.png

Exemplo#

Pesquisa foi realizada com alunos. Variáveis:

  • Id: identificação do aluno; Turma: A ou B;

  • Sexo: feminino (F) ou masculino (M);

  • Idade: em anos; Alt: altura em metros;

  • Peso: em quilogramas; Filhos: nº de filhos na famı́lia;

  • Fuma: hábito de fumar: sim (S) ou não (N);

  • Toler: tolerância ao cigarro: (I) indiferente; (P) incomoda pouco; (M) incomoda muito;

  • Exerc.: horas de atividade fı́sica, por semana;

  • Cine: nº. de vezes que vai ao cinema por semana;

  • OpCine: opinião a respeito das salas de cinema na cidade: (B) regular a boa; (M) muito boa;

  • TV: horas gastas assistindo TV, por semana;

  • OpTV: opinião a respeito da qualidade da programação na TV: (R) ruim; (M) média; (B) boa; (N) não sabe.

Organização dos dados#

  • A partir de um conjunto de dados coletado, a questão é:

    • Como extrair informações a respeito de uma ou mais caracterı́sticas de interesse?

  • Basicamente temos duas opções:

    • Tabelas de frequência;

    • Gráficos.

  • O importante é levar em consideração a natureza dos dados.

Tipos de variáveis#

image.png

Organização de Dados#

  • Uma tı́pica tabela de dados brutos contém:

    • Variáveis (caracterı́sticas, medições, etc) nas colunas.

    • Sujeito (indivı́duo, objetos, etc) nas linhas.

  • Tipos de variáveis:

    • Qualitativa nominal: Turma, Sexo, Fuma.

    • Qualitativa ordinal: Toler, OpCine, OpTV.

    • Quantitativa discreta: Idade, Filhos, Exerc, Cine, TV.

    • Quantitativa contı́nua: Alt, Peso.

Tabelas de frequência#

  • A tabela de dados brutos pode ser muito longa, portanto será difı́cil extrair alguma informação.

  • As tabelas de frequência ajudam a resumir a informação da variável de interesse.

  • Vamos usar 3 tipos de frequência:

    • Frequência absoluta: contagem de cada valor observado. Representado por \(n_i\) o número de indivı́duos com a caracterı́stica i.

    • Frequência relativa: número de indivı́duos com a caracterı́stica i dividido pelo total de indivı́duos n, ou seja \(f_i = \frac{n_i}{n}\).

  • Frequência acumulada: frequência (absoluta ou relativa) acumulada até um certo valor, obtida pela soma das frequências de todos os valores da variável, menores ou iguais ao valor considerado.

Hide code cell source
# HIDE CODE
import pandas as pd

df = pd.read_excel('questionario.xls')

df.head()
Id Turma Sexo Idade Alt Peso Filhos Fuma Toler Exerc Cine OpCine TV OpTV
0 1 A F 17 1.60 60.5 2 NAO P 0 1 B 16 R
1 2 A F 18 1.69 55.0 1 NAO M 0 1 B 7 R
2 3 A M 18 1.85 72.8 2 NAO P 5 2 M 15 R
3 4 A M 25 1.85 80.9 2 NAO P 5 2 B 20 R
4 5 A F 19 1.58 55.0 1 NAO M 2 2 B 5 R

Tabela de frequência - qualitativa nominal#

Hide code cell source
# HIDE CODE
df['Turma'].value_counts()
Turma
A    26
B    24
Name: count, dtype: int64
Hide code cell source
# HIDE CODE
df['Turma'].value_counts()/50
Turma
A    0.52
B    0.48
Name: count, dtype: float64
Hide code cell source
# HIDE CODE
tab_fr = pd.concat([df['Turma'].value_counts(),
                       df['Turma'].value_counts()/50],
                      axis=1)
tab_fr.columns = ['Frequência absoluta', 'Frequência relativa']
tab_fr
Frequência absoluta Frequência relativa
Turma
A 26 0.52
B 24 0.48

Neste caso não faz sentido usar frequência acumulada.

Tabela de frequência - qualitativa ordinal#

Hide code cell source
# HIDE CODE
tab_fr = pd.concat([df['OpTV'].value_counts(),
                    df['OpTV'].value_counts()/50,
                    (df['OpTV'].value_counts()/50).cumsum()],
                    axis=1)
tab_fr.columns = ['Frequência absoluta', 'Frequência relativa', 'Frequência acumulada']
tab_fr
Frequência absoluta Frequência relativa Frequência acumulada
OpTV
R 39 0.78 0.78
N 7 0.14 0.92
B 3 0.06 0.98
M 1 0.02 1.00

Tabela de frequência - quantitativa discreta#

Hide code cell source
# HIDE CODE
tab_fr = pd.concat([df['Idade'].value_counts(),
                    df['Idade'].value_counts()/50,
                    (df['Idade'].value_counts()/50).cumsum()],
                    axis=1)
tab_fr.columns = ['Frequência absoluta', 'Frequência relativa', 'Frequência acumulada']
tab_fr.sort_index(inplace=True)
tab_fr
Frequência absoluta Frequência relativa Frequência acumulada
Idade
17 9 0.18 0.62
18 22 0.44 0.44
19 7 0.14 0.76
20 4 0.08 0.84
21 3 0.06 0.90
23 2 0.04 0.98
24 1 0.02 1.00
25 2 0.04 0.94

Tabela de frequência - quantitativa contı́nua#

  • No caso de quantitativas contı́nuas não faz sentido contar cada valor pois podem existir muitos (potencialmente infinito).

  • A solução é criar classes ou faixas de valores, e contar o número de ocorrências dentro destas classes.

  • Para definir as classes:

    • Defina a amplitude da classe, de maneira que se obtenham de 5 a 8 classes (de mesma amplitude).

    • Identifique os valores máximo e mı́nimo da variável e construa as classes de maneira que inclua todos os valores.

  • As classes de valores podem seguir um dos formatos:

Hide code cell source
# HIDE CODE
%%capture
from matplotlib import pyplot as plt

h = plt.hist(df['Peso'], bins=10)
UsageError: Line magic function `%%capture` not found.
h
(array([ 7.,  8., 15.,  6.,  2.,  5.,  1.,  2.,  3.,  1.]),
 array([44. , 49.1, 54.2, 59.3, 64.4, 69.5, 74.6, 79.7, 84.8, 89.9, 95. ]),
 <BarContainer object of 10 artists>)
Hide code cell source
# HIDE CODE
%%capture
h = plt.hist(df['Peso'], bins=[40, 50, 60, 70, 80, 90, 100])
Hide code cell source
# HIDE CODE
pd.DataFrame([h[0], h[0]/50, (h[0]/50).cumsum()],
             index=['Frequência absoluta', 'Frequência relativa', 'Frequência acumulada']).T
Frequência absoluta Frequência relativa Frequência acumulada
0 8.0 0.16 0.16
1 22.0 0.44 0.60
2 8.0 0.16 0.76
3 6.0 0.12 0.88
4 5.0 0.10 0.98
5 1.0 0.02 1.00

Tabela de frequência - quantitativa discreta (muitos valores)#

  • Considerando a variável TV.

  • Apesar de ser discreta, o número de valores únicos é muito grande e não seria útil contar as frequências de cada valor.

  • Neste caso, utiliza-se o mesmo procedimento usado para quantitativas contı́nuas

    • Foram construı́das 6 classes de amplitude \(6^3\).

Hide code cell source
# HIDE CODE
%%capture
h = plt.hist(df['TV'], bins=[0, 6, 12, 18, 24, 30, 36])
Hide code cell source
# HIDE CODE
pd.DataFrame([h[0], h[0]/50, (h[0]/50).cumsum()],
             index=['Frequência absoluta', 'Frequência relativa', 'Frequência acumulada']).T
Frequência absoluta Frequência relativa Frequência acumulada
0 14.0 0.28 0.28
1 17.0 0.34 0.62
2 11.0 0.22 0.84
3 4.0 0.08 0.92
4 3.0 0.06 0.98
5 1.0 0.02 1.00

Representação gráfica#

  • Podemos visualizar as tabelas através de gráficos.

  • Existe um tipo de gráfico adequado para cada tipo de variável.

  • Cuidado deve ser tomado com representações visuais pois um gráfico desproporcional pode gerar interpretações distorcidas.

  • As principais representações gráficas são:

    • Diagrama circular (setores ou “pizza”);

    • Gráfico de barras;

    • Histogramas;

    • Boxplots.

Diagrama circular#

  • Adequado para variáveis qualitativas nominal e ordinal.

  • O uso deste tipo de gráfico deve ser evitado, pois pode ser de difı́cil interpretação.

Hide code cell source
# HIDE CODE
df['Toler'].value_counts()
Toler
P    21
M    19
I    10
Name: count, dtype: int64
Hide code cell source
# HIDE CODE
df['Toler'].value_counts().index.values
array(['P', 'M', 'I'], dtype=object)
Hide code cell source
# HIDE CODE
plt.pie(df['Toler'].value_counts(),
        labels=df['Toler'].value_counts().index.values,
        autopct='%1.1f%%')
([<matplotlib.patches.Wedge at 0x79f2908faca0>,
  <matplotlib.patches.Wedge at 0x79f2908fabe0>,
  <matplotlib.patches.Wedge at 0x79f2911fef10>],
 [Text(0.27355891977302554, 1.065441465972024, 'P'),
  Text(-0.8475646353272168, -0.7011663061946446, 'M'),
  Text(0.8899186272232006, -0.646563869173939, 'I')],
 [Text(0.14921395623983208, 0.5811498905301948, '42.0%'),
  Text(-0.4623079829057546, -0.3824543488334425, '38.0%'),
  Text(0.4854101603035639, -0.35267120136760305, '20.0%')])
../../_images/227e2f74696eed5272fe59a38580c56134353efc62181b517f4c647ba80edebd.png

Gráfico de barras#

  • Adequado para variáveis qualitativas nominal/ordinal e quantitativa discreta (poucos valores distintos).

  • Podem ser usadas as frequências absolutas ou relativas.

Hide code cell source
# HIDE CODE
plt.bar(df['Toler'].value_counts().index.values,
        df['Toler'].value_counts())
<BarContainer object of 3 artists>
../../_images/363af0e2bd14f9c77c96116b2e4bb52ba3e78f59a306d7c17a14399cca25e26d.png
Hide code cell source
# HIDE CODE
plt.bar(df['Toler'].value_counts().index.values,
        df['Toler'].value_counts()/50)
<BarContainer object of 3 artists>
../../_images/9ce83331a9514ee3e813e7cc71be669031661a98ca3fa5d890e1c54314aea65d.png
Hide code cell source
# HIDE CODE
plt.rcParams["figure.figsize"] = (10,8)
fig, (ax1, ax2) = plt.subplots(1, 2)
fig.suptitle('Subplots combinados horizontalmente')

ax1.bar(df['Toler'].value_counts().index.values,
        df['Toler'].value_counts())
ax1.set_ylabel('Frequência absoluta')

ax2.bar(df['Toler'].value_counts().index.values,
        df['Toler'].value_counts()/50)
ax2.set_ylabel('Frequência relativa')
Text(0, 0.5, 'Frequência relativa')
../../_images/9a0800eecb1851ada2126477611130438ccc55d62f8fa11e29b8f3f7ad68697d.png
Hide code cell source
# HIDE CODE
plt.rcParams["figure.figsize"] = plt.rcParamsDefault["figure.figsize"]
Hide code cell source
# HIDE CODE
pd.crosstab(df['Toler'], df['Turma']).plot(kind='bar')
<Axes: xlabel='Toler'>
../../_images/23486e8259322d06cee98308dabce377f4560bf5a99d61b3e300ad400df945fc.png

Histograma#

  • Adequado para quantitativa contı́nua.

  • Altura de cada retângulo é a densidade definida pelo quociente da área pela amplitude da faixa, \(h = \frac{f_i}{AMP}\).

Hide code cell source
# HIDE CODE
import numpy as np

fig, ax = plt.subplots()
ax.hist(df['Peso'], bins=[40, 50, 60, 70, 80, 90, 100], weights=np.zeros_like(df['Peso']) + 1. / df['Peso'].size)
ax.set_ylabel('Frequência relativa')
Text(0, 0.5, 'Frequência relativa')
../../_images/67319ab930e50115bc3e4a9487ea26b094309f3f2e164cdd53d72b944616ccf5.png
Hide code cell source
# HIDE CODE
fig, ax = plt.subplots()
ax.hist(df['Peso'], bins=[40, 50, 60, 70, 80, 90, 100], density=True)
ax.set_ylabel('Densidade')
Text(0, 0.5, 'Densidade')
../../_images/fe6fbfe7af62916a2ba27e2fc1a57ade852fa4cf111ae3efff2ba793f177067e.png

Mediana e quartis#

  • Mediana: valor da variável que divide o conjunto de dados ordenado em dois subgrupos de mesmo tamanho.

  • Quartis: valores da variável que divide o conjunto de dados ordenados em quatro subgrupos de mesmo tamanho.

  • Posição dos quartis:

    • Q1 = 0.25 · (N + 1) e arredonde.

    • Q2 = média dos valores nas posições (N/2) e (N/2) + 1 se N par e

    • Q2 = (N + 1)/2 se N ı́mpar.

    • Q3 = 0.75 · (N + 1) e arredonde.

  • Exemplo: Conside o conjunto de dados: 8.43(1), 8.65(2), 9.96(3), 10.91(6), 10.46(4) e 10.83(5).

    • Q1 = 0.25 · 7 = 1.75 ≈ 2, ou seja 8.65.

    • Q2 = média dos valores nas posições 3 e 4, ou seja, (9.96 + 10.46)/2 = 10.21.

    • Q3 = 0.75 · 7 = 5.25 ≈ 5, ou seja, 10.83.

Boxplots#

Excelente para explorar relações entre qualitativas e contı́nuas.

Hide code cell source
# HIDE CODE
df.boxplot(['Peso'])
<Axes: >
../../_images/068c46b8b45f7f712ef5a9c37b590633805b4c359aec7fee9839f37505a188c0.png
Hide code cell source
# HIDE CODE
# Como obter os quartis representados no boxplot
df['Peso'].quantile([.25, .5, .75])
0.25    52.125
0.50    58.000
0.75    67.875
Name: Peso, dtype: float64
Hide code cell source
# HIDE CODE
# Descrever os componentes principais do boxplot
plt.boxplot(df['Peso'])
plt.hlines(58, 0.5, 1.5, linestyles='dashed', colors='orange')
plt.hlines(52.125, 0.5, 1.5, linestyles='dashed', colors='blue')
plt.hlines(67.875, 0.5, 1.5, linestyles='dashed', colors='red')
<matplotlib.collections.LineCollection at 0x79f25829a490>
../../_images/8deb424340592ce256f50aaf163a89f19d3a1d9d84fa28d436648735862176ea.png
Hide code cell source
# HIDE CODE
# a altura da caixa é dada pela
# amplitude interquartil (AIQ) ou do inglês (IQR)
iqr = 67.875-52.125

# Para os limites superior e inferior, utilizamos
# os pontos dos dados mais próximos das fórmulas abaixo
# Q3+1.5*IQR
whigh = df.loc[df['Peso']<= (67.875+1.5*iqr), 'Peso'].max()
# Q1-1.5*IQR
wlow = df.loc[df['Peso']>= (52.125-1.5*iqr), 'Peso'].min()
Hide code cell source
# HIDE CODE
# Representação dos limites inferior e superior
plt.boxplot(df['Peso'])
plt.hlines(whigh, 0.5, 1.5, linestyles='dashed', colors='orange')
plt.hlines(wlow, 0.5, 1.5, linestyles='dashed', colors='orange')
<matplotlib.collections.LineCollection at 0x79f2581b51c0>
../../_images/92ebe65594e5308de6595fa08e12605ed7fdcc1fc917c5d89cae0c06ff8b15d8.png
Hide code cell source
# HIDE CODE
import seaborn as sns

sns.boxplot(y=df["Peso"])
<Axes: ylabel='Peso'>
../../_images/19d548624cbd44ae13733a6e29848d4cb6ce387a48d789c0ba3c430c9ef82055.png
Hide code cell source
# HIDE CODE
fig, ax = plt.subplots()
ax.boxplot(df.loc[df['Turma']=='A', 'Peso'], patch_artist=True,  showmeans=True, positions=[1])
ax.boxplot(df.loc[df['Turma']=='B', 'Peso'], patch_artist=True,  showmeans=True, positions=[2])
ax.autoscale()
ax.set(xticks=[1,2], xticklabels=['A','B'])
[[<matplotlib.axis.XTick at 0x79f258b761f0>,
  <matplotlib.axis.XTick at 0x79f258b761c0>],
 [Text(1, 0, 'A'), Text(2, 0, 'B')]]
../../_images/6aecfd19ceefd662fabb679d9d4945d151788d1e87538c48ffb51f36ece901a2.png
Hide code cell source
# HIDE CODE
sns.boxplot(data=df, x="Turma", y="Peso", hue="Turma")
<Axes: xlabel='Turma', ylabel='Peso'>
../../_images/742bcc207249f7aeda6cbe18f709178714739487414236caba0369f5c0869408.png

Diagrama de dispersão#

Adequado para explorar a relação entre variáveis quantitativas.

Hide code cell source
# HIDE CODE
# prompt: genetare scatter plot of weigth and height

plt.scatter(df['Peso'], df['Alt'])
plt.xlabel('Peso')
plt.ylabel('Altura')
plt.title('Gráfico de Dispersão: Peso vs Altura')
plt.show()
../../_images/6eb24cd9454b35b848ea8e89af292c93dcf62a5193af8243645767d45a7c7969.png

Exemplo complexo#

Vamos utilizar os dados do portal Gapminder para mostrar o diagrama de bolhas (bubble plot), assim como a criação de um gráfico dinâmico com uso de inteligência artificial.

import pandas as pd
from IPython.display import display, HTML

pop = pd.read_csv('pop.csv')
pop.head()
country 1800 1801 1802 1803 1804 1805 1806 1807 1808 ... 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100
0 Afghanistan 3.28M 3.28M 3.28M 3.28M 3.28M 3.28M 3.28M 3.28M 3.28M ... 124M 125M 126M 126M 127M 128M 128M 129M 130M 130M
1 Angola 1.57M 1.57M 1.57M 1.57M 1.57M 1.57M 1.57M 1.57M 1.57M ... 139M 140M 142M 143M 144M 145M 147M 148M 149M 150M
2 Albania 400k 402k 404k 405k 407k 409k 411k 413k 414k ... 1.34M 1.32M 1.3M 1.29M 1.27M 1.25M 1.23M 1.22M 1.2M 1.18M
3 Andorra 2650 2650 2650 2650 2650 2650 2650 2650 2650 ... 52.8k 52.1k 51.5k 50.8k 50.2k 49.6k 49k 48.4k 47.8k 47.2k
4 UAE 40.2k 40.2k 40.2k 40.2k 40.2k 40.2k 40.2k 40.2k 40.2k ... 24.1M 24.3M 24.5M 24.7M 25M 25.2M 25.4M 25.7M 25.9M 26.1M

5 rows × 302 columns

ch_wom = pd.read_csv('children_per_woman_total_fertility.csv')
ch_wom.head()
country 1800 1801 1802 1803 1804 1805 1806 1807 1808 ... 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100
0 Afghanistan 7.00 7.00 7.00 7.00 7.00 7.00 7.00 7.00 7.00 ... 2.16 2.14 2.13 2.12 2.11 2.10 2.09 2.08 2.07 2.06
1 Angola 6.93 6.93 6.93 6.93 6.93 6.93 6.93 6.94 6.94 ... 2.24 2.23 2.22 2.21 2.20 2.18 2.17 2.16 2.15 2.14
2 Albania 4.60 4.60 4.60 4.60 4.60 4.60 4.60 4.60 4.60 ... 1.48 1.48 1.49 1.49 1.49 1.49 1.49 1.49 1.50 1.49
3 Andorra 2.11 2.11 2.11 2.11 2.11 2.11 2.11 2.11 2.11 ... 1.40 1.40 1.40 1.40 1.40 1.40 1.40 1.41 1.41 1.41
4 UAE 6.94 6.94 6.94 6.94 6.94 6.94 6.94 6.94 6.94 ... 1.44 1.44 1.45 1.45 1.45 1.45 1.45 1.46 1.46 1.46

5 rows × 302 columns

gdp_pcap = pd.read_csv('gdp_pcap.csv')
gdp_pcap.head()
country 1800 1801 1802 1803 1804 1805 1806 1807 1808 ... 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100
0 Afghanistan 481 481 481 481 481 481 481 481 481 ... 4680 4790 4910 5020 5140 5260 5380 5510 5640 5780
1 Angola 373 374 376 378 379 381 383 385 386 ... 24.5k 25k 25.6k 26.1k 26.6k 27.1k 27.7k 28.2k 28.8k 29.3k
2 Albania 469 471 472 473 475 476 477 479 480 ... 54.5k 55.1k 55.7k 56.3k 56.9k 57.4k 58k 58.6k 59.2k 59.8k
3 Andorra 1370 1370 1370 1380 1380 1380 1390 1390 1390 ... 79.9k 80.2k 80.4k 80.7k 81k 81.3k 81.5k 81.8k 82k 82.3k
4 UAE 1140 1150 1150 1150 1160 1160 1170 1170 1180 ... 92.6k 92.6k 92.6k 92.7k 92.7k 92.7k 92.8k 92.8k 92.8k 92.9k

5 rows × 302 columns

pop.shape[1]==ch_wom.shape[1]==gdp_pcap.shape[1]
True
pop.loc[(pop['country']=='China'), '2020']
32    1.43B
Name: 2020, dtype: object
# Prepare data for the plot
year = '2020'
data2020 = pop[['country', year]].merge(
    ch_wom[['country', year]], on='country'
).merge(
    gdp_pcap[['country', year]], on='country'
)
data2020.index = data2020['country']
data2020.drop(columns=['country'], inplace=True)
data2020.head()
2020_x 2020_y 2020
country
Afghanistan 39.1M 5.15 1970
Angola 33.5M 5.37 6030
Albania 2.87M 1.37 13.3k
Andorra 77.4k 1.03 49.7k
UAE 9.45M 1.29 67.4k
data2020.loc[['China', 'India']]
2020_x 2020_y 2020
country
China 1.43B 1.24 16.3k
India 1.4B 2.05 6140
data2020.columns = ['pop', 'ch_wom', 'gdp_pcap']
data2020.fillna(0, inplace=True)
data2020['pop'] = data2020['pop'].replace({'B': 'e9', 'M': 'e6', 'k': 'e3'}, regex=True).apply(pd.eval)
data2020['gdp_pcap'] = data2020['gdp_pcap'].replace({'k': 'e3'}, regex=True).apply(pd.eval)
data2020.head()
pop ch_wom gdp_pcap
country
Afghanistan 39100000.0 5.15 1970.0
Angola 33500000.0 5.37 6030.0
Albania 2870000.0 1.37 13300.0
Andorra 77400.0 1.03 49700.0
UAE 9450000.0 1.29 67400.0
data2020['pop'].isna().sum()
0
import seaborn as sns
sns.set_theme(rc={'figure.figsize':(8,4)})

# Plot miles per gallon against horsepower with other semantics
sns.relplot(x="gdp_pcap", y="ch_wom",  size="pop",
            sizes=(40, 4000), alpha=.5,
            height=6, data=data2020, legend=False)
<seaborn.axisgrid.FacetGrid at 0x7f976ae3ef70>
../../_images/005ff9a5a4a47812a5712b83b2157739f413f29fca969be8d36e935c92eb9825.png
plt.scatter(x=data2020["gdp_pcap"], y=data2020["ch_wom"],
            s=data2020["pop"]/10e5, alpha=0.5)
<matplotlib.collections.PathCollection at 0x7f976aa32a00>
../../_images/c2fca28ae68f73fd78ce87432afcd9f2ee0d8fd09b4979fddcc750924145c9c7.png

Podemos usar uma inteligência artificial, GitHub Copilot ou Google Gemini, para gerar o código abaixo a partir do terminal (prompt):

gere um gráfico dinâmico com plotly express que mostre a relação entre PIB per capita e filhos por mulher, com o tamanho dos pontos representando a população, para o ano de 2020

import plotly.express as px
import plotly.offline as py

# Select a year for visualization
year = '2020'

# Prepare data for the plot
df = pop[['country', year]].merge(
    ch_wom[['country', year]], on='country'
).merge(
    gdp_pcap[['country', year]], on='country'
)

df.columns = ['country', 'population', 'children_per_woman', 'gdp_per_capita']

# Convert columns to numeric
df['population'] = df['population'].replace({'B': 'e9', 'M': 'e6', 'k': 'e3'}, regex=True).apply(pd.eval)
df['children_per_woman'] = pd.to_numeric(df['children_per_woman'], errors='coerce')
df['gdp_per_capita'] = df['gdp_per_capita'].replace({'k': 'e3'}, regex=True).apply(pd.eval)

# Create interactive bubble plot
fig = px.scatter(
    df,
    x='gdp_per_capita',
    y='children_per_woman',
    size='population',
    hover_name='country',
    title=f'Bubble Plot for {year}',
    labels={
        'gdp_per_capita': 'GDP per Capita',
        'children_per_woman': 'Children per Woman',
        'population': 'Population'
    },
    size_max=60,
    width=800, height=400
)
#fig.show()
py.plot(fig, filename='figure_1.html', auto_open=True)
display(HTML('figure_1.html'))

Usar o seguinte terminal para criar uma animação: “generate the sample plot as above as an annimation by year”

import plotly.express as px

# Prepare data for animation
years = [str(y) for y in range(1960, 2021)]  # Use years available in all datasets

# Merge all years into a single dataframe for animation
dfs = []
for y in years:
    # Some years may be missing in some countries, so use inner join
    temp = pop[['country', y]].merge(
        ch_wom[['country', y]], on='country', how='inner'
    ).merge(
        gdp_pcap[['country', y]], on='country', how='inner'
    )
    temp.columns = ['country', 'population', 'children_per_woman', 'gdp_per_capita']
    temp['year'] = y
    # Convert columns to numeric
    temp['population'] = temp['population'].replace({'B': 'e9', 'M': 'e6', 'k': 'e3'}, regex=True).apply(pd.eval)
    temp['children_per_woman'] = pd.to_numeric(temp['children_per_woman'], errors='coerce')
    temp['gdp_per_capita'] = temp['gdp_per_capita'].replace({'k': 'e3'}, regex=True).apply(pd.eval)
    dfs.append(temp)

df_anim = pd.concat(dfs, ignore_index=True)

# Create animated bubble plot
fig_anim = px.scatter(
    df_anim,
    x='gdp_per_capita',
    y='children_per_woman',
    size='population',
    hover_name='country',
    animation_frame='year',
    title='Bubble Plot Animation by Year',
    labels={
        'gdp_per_capita': 'GDP per Capita',
        'children_per_woman': 'Children per Woman',
        'population': 'Population'
    },
    size_max=60
)
py.plot(fig, filename='figure_2.html')
display(HTML('figure_2.html'))
#fig_anim.show()

Prática complementar OPCIONAL#

Código python: Abra com Colab

Bibliografia#

[BM09]

Wilton de Oliveira Bussab and Pedro Alberto Morettin. Estatística básica. Saraiva, 2009.

[CW17]

Kieth A Carlson and Jennifer R Winquist. An introduction to statistics: An active learning approach. Sage Publications, 2017.

[MagalhaesdL02]

Marcos Nascimento Magalhães and Antonio Carlos Pedroso de Lima. Noções de probabilidade e estatística. Volume 5. Editora da Universidade de São Paulo, 2002.

[Mar15]

Edson Zangiacomi Martinez. Bioestatística para os cursos de graduação da área da saúde. Blucher São Paulo, 2015.